import uiconst
import uicls
import uiutil
import uitest
import uthread
import blue
import base
import trinity

class Container(uitest.BaseDecoCore, uicls._GetDecoMetaclassInst('trinity.Tr2Sprite2dContainer')):
    __guid__ = 'uicls.NewContainer'
    default_name = 'container'
    default_clipChildren = False
    default_pickRadius = 0
    default_opacity = 1.0
    default_align = uiconst.TOALL
    default_state = uiconst.UI_PICKCHILDREN

    def ApplyAttributes(self, attributes):
        uitest.BaseDecoCore.ApplyAttributes(self, attributes)
        self.depthMin = -1.0
        self.depthMax = 1.0
        self._dragging = False
        self._dragAllowed = False
        self._dragData = None
        if attributes.__gotShape__:
            return 
        self.opacity = attributes.get('opacity', self.default_opacity)
        self.SetClipState(attributes.get('clipChildren', self.default_clipChildren))



    def GetAlignmentBudgetForChild(self, child):
        (l, t, w, h,) = self.GetAbsolute()
        l = t = 0
        for mychild in self.children:
            if (mychild == child):
                break
            if ((mychild.display == False) or (not hasattr(mychild, 'GetAlign'))):
                continue
            mcAlign = mychild.GetAlign()
            if (mcAlign not in self.__push_alignments__):
                continue
            (padLeft, padTop, padRight, padBottom,) = mychild.GetPadding()
            if (mcAlign == uiconst.TOLEFT):
                l += ((mychild.displayWidth + padLeft) + padRight)
                w -= ((mychild.displayWidth + padLeft) + padRight)
            elif (mcAlign == uiconst.TORIGHT):
                w -= ((mychild.displayWidth + padLeft) + padRight)
            elif (mcAlign == uiconst.TOTOP):
                t += ((mychild.displayHeight + padTop) + padBottom)
                h -= ((mychild.displayHeight + padTop) + padBottom)
            else:
                if (mcAlign == uiconst.TOBOTTOM):
                    h -= ((mychild.displayHeight + padTop) + padBottom)

        return (l,
         t,
         w,
         h)



    def AddChild(self, child, idx = -1):
        if (idx == -1):
            idx = len(self.children)
        self.children.insert(idx, child)



    def RemoveChild(self, child):
        if self.destroyed:
            return 
        doUpdate = False
        if (child in self.children):
            idx = self.children.index(child)
            if (child.GetAlign() in self.__push_alignments__):
                doUpdate = True
            self.children.remove(child)
        self.UpdateAlignment()



    def Flush(self):
        for child in self.children[:]:
            if hasattr(child, 'Close'):
                if not getattr(child, 'destroyed', 0):
                    child.Close()
            else:
                self.children.remove(child)




    def FindChild(self, *names, **kwds):
        ret = None
        for name in names:
            ret = self._FindChildByName(name)
            if not ret:
                if kwds.get('raiseError', False):
                    raise RuntimeError('ChildNotFound', (self.name, names))
                return 

        if ((not ret) and kwds.get('raiseError', False)):
            raise RuntimeError('ChildNotFound', (self.name, names))
        return ret



    def Find(self, blueTypeName):

        def FindType(under, typeName, addto):
            if (under.__bluetype__ == typeName):
                addto.append(under)
            if hasattr(under, 'children'):
                for each in under.children:
                    FindType(each, typeName, addto)



        ret = []
        for child in self.children:
            FindType(child, blueTypeName, ret)

        return ret



    def GetChild(self, *names):
        return self.FindChild(*names, **{'raiseError': True})



    def _FindChildByName(self, name):
        for child in self.children:
            if (child.name == name):
                return child
            if hasattr(child, 'children'):
                ret = child._FindChildByName(name)
                if (ret is not None):
                    return ret




    def UpdateAlignment(self, budget = None, kickChilds = False):
        preDisplayWidth = self.displayWidth
        preDisplayHeight = self.displayHeight
        if (self == uicore.desktop):
            self.displayX = -0.5
            self.displayY = -0.5
            self.displayWidth = trinity.device.width
            self.displayHeight = trinity.device.height
            self._alignmentDirty = False
        else:
            uitest.BaseDecoCore.UpdateAlignment(self)
        kickChilds = (kickChilds or bool(((preDisplayWidth != self.displayWidth) or (preDisplayHeight != self.displayHeight))))
        childbudget = (0,
         0,
         self.displayWidth,
         self.displayHeight)
        for child in self.children:
            if hasattr(child, 'UpdateAlignment'):
                if kickChilds:
                    child._alignmentDirty = True
                retbudget = child.UpdateAlignment(budget=childbudget)
                if retbudget:
                    childbudget = retbudget




    def SetClipState(self, state):
        self.clip = state



    def GetClipState(self):
        return self.clip




